package com.ttx.single.lab.service.sharding;

import com.ttx.single.lab.mapper.OrderItemMapper;
import com.ttx.single.lab.mapper.OrderMapper;
import com.ttx.single.lab.mapper.OrderMappingMapper;
import com.ttx.single.lab.model.bo.OrderBO;
import com.ttx.single.lab.model.bo.OrderItemBO;
import com.ttx.single.lab.model.dataobject.OrderDO;
import com.ttx.single.lab.model.dataobject.OrderItemDO;
import com.ttx.single.lab.model.dataobject.OrderMapping;
import com.ttx.single.lab.model.dto.PlaceOrderDto;
import com.ttx.single.lab.service.CommonDoubleWriteOrderService;
import com.ttx.single.lab.service.OrderService;
import com.ttx.single.lab.service.defaultimpl.OrderServiceImpl;
import com.ttx.suite.web.model.bo.PageBO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * 4
 * # 1 使用uid的初始下单  2 下单双写，以单库读写为主  3  下单双写， 以分库读写为主 4 下单只写在分库
 * 分库分表后的操作
 * @author TimFruit
 * @date 20-4-8 下午6:44
 */
@Service
@Slf4j
@Transactional(transactionManager = "shardingTransactionManager") //使用sharding事务管理
public class OrderServiceShardingImpl extends OrderServiceImpl implements OrderService ,InitializingBean,ApplicationContextAware {
    //分库
    @Autowired
    @Qualifier("shardingOrderMapper")
    OrderMapper shardingOrderMapper;
    @Autowired
    @Qualifier("shardingOrderItemMapper")
    OrderItemMapper shardingOrderItemMapper;
    @Autowired
    OrderMappingMapper orderMappingMapper;

    @Autowired
    CommonDoubleWriteOrderService doubleWriteOrderService;

    @Autowired
    ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //是为了复用listUserOrderPage方法
        log.info("xxxxxx=========================");

        log.info("原订单服务的父类的orderMapper为: "+super.orderMapper);
        log.info("原订单服务的父类的orderItemMapper为: "+super.orderItemMapper);

        super.orderMapper=shardingOrderMapper;
        super.orderItemMapper=shardingOrderItemMapper;

        log.info("修改分库分表订单服务的父类的orderMapper为: "+super.orderMapper);
        log.info("修改分库分表订单服务的父类的orderItemMapper为: "+super.orderItemMapper);
        log.info("xxxxxx=========================");

    }


    @Transactional(transactionManager = "shardingTransactionManager")
    @Override
    public void placeOrder(PlaceOrderDto orderDto) {
        doubleWriteOrderService.placeOrder(shardingOrderMapper,shardingOrderItemMapper,orderDto);
    }


    //TODO 修改

    @Override
    public PageBO<OrderBO> listUserOrderPage(Long userId, Integer pageNum, Integer pageSize) {
        return super.listUserOrderPage(userId,pageNum,pageSize);
    }




    @Override
    public OrderBO selectOrder(Long orderId) {

        OrderDO orderDO=null;
        //这里使用了order_id和user_id的映射来查找库，减少库的查找次数

        //TODO 这里可以使用缓存优化
        Integer userId=orderMappingMapper.selectUserIdByOrderId(orderId);




        if(userId==null){//这里可以缓存优化
            log.warn("订单号"+orderId+"找不到对应的userId, sharding jdbc将会全局搜索");
            orderDO=shardingOrderMapper.selectByOrderId(orderId);
            if(orderDO!=null){//保存记录
                OrderMapping mapping=new OrderMapping();
                mapping.setOrderId(orderDO.getOrderId());
                mapping.setUserId(orderDO.getUserId());
                mapping.setCreateTime(new Date());
                mapping.setUpdateTime(new Date());
                orderMappingMapper.replace(mapping);
            }
        }else {
            orderDO=shardingOrderMapper.selectByOrderIdAndUserId(orderId, userId);
        }


        if(orderDO==null){
            return null;
        }


        List<OrderItemDO> itemDOS=null;

        if(userId==null){ //这里可以缓存优化
            itemDOS=shardingOrderItemMapper.listOrderItemByOrderId(orderId);
        }else {
            itemDOS=shardingOrderItemMapper.listOrderItemByOrderIdAndUserId(orderId, userId);
        }




        OrderBO orderBO=new OrderBO();
        BeanUtils.copyProperties(orderDO,orderBO);

        List<OrderItemBO> itemBOS=itemDOS.stream().map(itemDO->{
            OrderItemBO itemBO=new OrderItemBO();
            BeanUtils.copyProperties(itemDO, itemBO);
            return itemBO;
        }).collect(Collectors.toList());

        orderBO.setOrderItemBOList(itemBOS);

        return orderBO;
    }


    @Override
    public void cancelOrder(Long orderId, Integer userId) {
        Date date=new Date();
        doubleWriteOrderService.cancelOrder(shardingOrderMapper, orderId, userId,date);
    }
}
